#include <simulator/simulator.h>

std::shared_ptr<TargetMachine> Simulator::getDspMachine(){
    return m_targetMachine;
}

void Simulator::addTimer(std::shared_ptr<Timer> timer) {
    m_timers.push_back(timer);
}

void Simulator::loadInstIRIntoJit() {
    // 初始化一个llvm模块
    m_llvmJit->initializeModule("instructions");
    llvm::LLVMContext *llvmContext = m_llvmJit->getLLVMContext();
    llvm::Module *llvmModule = m_llvmJit->getCurModulePtr();
    auto irBuild = m_llvmJit->getIrBuilder();
    auto ee = m_llvmJit->getExecutionEngine();
    // 添加全局变量，以供ir函数执行
    addGlobalVariable(llvmContext, llvmModule);
    // 加载指令对应的ir函数到llvm jit执行引擎中
    for (auto &instProto: m_instProto)
        instProto->loadInstIRIntoJit(llvmContext, llvmModule, irBuild);
    // 将llvm中的全局变量映射到程序中的指定变量上
    addGlobalMapping(ee);
}

void Simulator::nextCycle() {
    m_timers[0]->incrementCycle();
}

void Simulator::addInstIntoDelayQueue(std::shared_ptr<Instruction> instruction) {
    u64 delay = instruction->getDelay();
    // 指令需要执行的所有时钟周期
    std::list<u64> allCycle;
    while (delay != 0) {
        allCycle.push_front(m_timers[0]->getCycle() + delay);
        --delay;
    }
    m_delayQueue.emplace(m_timers[0]->getCycle(), allCycle, instruction);
}

void Simulator::executeDelayInst() {
    // 通过while循环执行当前周期需要执行的延时指令
    while (!m_delayQueue.empty() && m_delayQueue.top().getTopCycle() == m_timers[0]->getCycle()) {
        // 取出一条需要当前周期执行的延时指令
        auto delayInstruction = m_delayQueue.top();
        auto instruction = delayInstruction.getInstruction();
        m_delayQueue.pop();
        // 执行延时指令
        instruction->execute(m_targetMachine, m_llvmJit,
                             static_cast<ExecutePhase>(m_timers[0]->getCycle() - instruction->getBaseCycle()));
        // 弹出延时指令执行周期列表中最早的执行周期，因为该周期的指令操作已被执行
        delayInstruction.popTopCycle();
        // 如果延时指令的周期队列不为空，将延时指令再次放入延时队列中
        if (!delayInstruction.isEmptyCycle())
            m_delayQueue.push(delayInstruction);
    }
}
